﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="LoggingServiceTests.cs" company="XamlNinja">
//   2011 Richard Griffin and Ollie Riches
// </copyright>
// <summary>
//   Logging service unit tests - we follow BDD principles, http://dannorth.net/introducing-bdd/
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace WP7Contrib.Logging.Tests
{
    using System;
    using System.Linq;
    using WP7Contrib.Logging;
    using Microsoft.Silverlight.Testing;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    [TestClass]
    public class LoggingServiceTests : SilverlightTest
    {
        [TestMethod]
        public void ShouldCreateLoggingService()
        {
            // cleans up any directories created...
            using (var helper = new DirectoryHelper())
            {
                // Given we can generate an application name...
                var applicationName = helper.GenerateDirectoryName();

                // When we create the logging service...
                using (new LoggingService(applicationName))
                {
                    // Then we don't expect any exceptions...
                }
            }
        }

        public void ShouldEnableLoggingService()
        {
            // cleans up any directories created...
            using (var helper = new DirectoryHelper())
            {
                // Given we can generate an application name...
                var applicationName = helper.GenerateDirectoryName();

                // Given we can create the logging service...
                using (var loggingService = new LoggingService(applicationName))
                {
                    // When we enable the logging service...
                    loggingService.Enable();

                    // Then we don't expect any exceptions...
                }
            }
        }

        [TestMethod]
        public void ShouldWriteMessage()
        {
            // cleans up any directories created...
            using (var helper = new DirectoryHelper())
            {
                // Given we can generate an application name...
                var applicationName = helper.GenerateDirectoryName();

                // Given we can create the logging service...
                using (var loggingService = new LoggingService(applicationName))
                {
                    // Given we can enable the logging service...
                    loggingService.Enable();

                    // When we write a message...
                    loggingService.Write("The answer is 42!");

                    // Then we don't expect any exceptions...
                }
            }
        }

        [TestMethod]
        public void ShouldNotifyWhenLogHasBeenModified()
        {
            // cleans up any directories created...
            using (var helper = new DirectoryHelper())
            {
                // Given we can generate an application name...
                var applicationName = helper.GenerateDirectoryName();

                // Given we can create the logging service...
                using (var loggingService = new LoggingService(applicationName))
                {
                    // Given we can enable the logging service...
                    loggingService.Enable();

                    // When we monitor when the log file is modified and write a message to the log...
                    var modified = false;
                    loggingService.LogModified += delegate { modified = true; };
                    loggingService.Write("The answer is 42!");
                    WaitUntilModifiedOrTimeout(ref modified);

                    // Then we expect to be notified of the modified log file...
                    Assert.IsTrue(modified);
                }
            }
        }

        [TestMethod]
        public void ShouldReadContentsOfPersistedLog()
        {
            // cleans up any directories created...
            using (var helper = new DirectoryHelper())
            {
                // Given we can generate an application name...
                var applicationName = helper.GenerateDirectoryName();

                // Given we can create the logging service...
                using (var loggingService = new LoggingService(applicationName))
                {
                    // Given we can enable the logging service and monitor for changes...
                    var modified = false;
                    loggingService.LogModified += delegate { modified = true; };
                    loggingService.Enable();

                    // Given we can write a message to the log...
                    var message = "My message " + Guid.NewGuid();
                    loggingService.Write(message);

                    // Given we can wait until the messages have been persisted...
                    WaitUntilModifiedOrTimeout(ref modified);

                    // When we get the messages from persisted log...
                    var messages = loggingService.Messages;

                    // Then we expect message to contain the message...
                    Assert.IsNotNull(messages);
                    Assert.IsTrue(messages.ToList().Count == 1);
                    Assert.IsNotNull(messages.Where(m => m.Contains(message)).FirstOrDefault());
                }
            }
        }

        [TestMethod]
        public void ShouldClearPersistedLog()
        {
            // cleans up any directories created...
            using (var helper = new DirectoryHelper())
            {
                // Given we can generate an application name...
                var applicationName = helper.GenerateDirectoryName();

                // Given we can create the logging service...
                using (var loggingService = new LoggingService(applicationName))
                {
                    // Given we can enable the logging service and monitor for changes...
                    var modified = false;
                    loggingService.LogModified += delegate { modified = true; };
                    loggingService.Enable();

                    // Given we can write a message to the log...
                    var message = "My message " + Guid.NewGuid();
                    loggingService.Write(message);

                    // Given we can wait until the messages have been persisted...
                    WaitUntilModifiedOrTimeout(ref modified);

                    // When we clear the messages from persisted log...
                    loggingService.Clear();
                    var messages = loggingService.Messages;

                    // Then we expect message to contain the message...
                    Assert.IsNotNull(messages);
                    Assert.IsTrue(messages.ToList().Count == 0);
                    Assert.IsNull(messages.Where(m => m.Contains(message)).FirstOrDefault());
                }
            }
        }

        private static void WaitUntilModifiedOrTimeout(ref bool modified)
        {
            var counter = 0;
            while (true)
            {
                if (counter == 20)
                {
                    break;
                }

                if (modified)
                {
                    break;
                }

                System.Threading.Thread.SpinWait(1000);
                counter++;
            }
        }
    }
}